
package com.xuecheng.ai.controller;

import com.alibaba.fastjson.JSON;
import com.xuecheng.ai.constant.AIModelConstant;
import com.xuecheng.api.client.ContentClient;
import com.xuecheng.api.client.LearningClient;
import com.xuecheng.api.dto.CoursePublish;
import com.xuecheng.api.dto.XcCourseTablesDTO;
import io.github.lnyocly.ai4j.listener.SseListener;
import io.github.lnyocly.ai4j.platform.openai.chat.entity.ChatCompletion;
import io.github.lnyocly.ai4j.platform.openai.chat.entity.ChatMessage;
import io.github.lnyocly.ai4j.service.IChatService;
import io.github.lnyocly.ai4j.service.PlatformType;
import io.github.lnyocly.ai4j.service.factor.AiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/chat")
@RequiredArgsConstructor
@Api(tags = "ai学习助手管理")
public class ChatController {

    /**
     * AI服务
     */
    private final AiService aiService;

    /**
     * 学习服务
     */
    private final LearningClient learningClient;

    /**
     * 内容服务
     */
    private final ContentClient contentClient;

    /**
     * 聊天记录
     */
    private final List<ChatMessage> history = new ArrayList<>();

    /**
     * 提示词
     */
    private String prompt = "你是一个在线学习平台的AI助手，负责解答课程相关问题。\n" +
            "        用户当前学习的课程有：%s 排序规则是从最近学习时间递减\n"+
            "        请根据用户问题提供专业、简洁的回答，避免无关内容。\n" +
            "        如果问题与学习无关，请提示用户专注于课程内容。";

    /**
     * 获取聊天流式数据
     *
     * @param question 问题
     * @return 聊天流式数据
     */
    @GetMapping("/stream")
    @ApiOperation("获取聊天流式数据")
    public SseEmitter getChatMessageStream(@RequestParam("question") String question, @RequestParam("userId") String userId) {
        List<XcCourseTablesDTO> courseTables = learningClient.getCourseTables(userId);
        // 0. 根据用户选的课程id获取课程详细信息
        List<CoursePublish> coursePublishes = new ArrayList<>();
        courseTables.stream().map(XcCourseTablesDTO::getCourseId).collect(Collectors.toList()).forEach(
                courseId -> {
                    CoursePublish coursePublish = contentClient.getById(courseId);
                    coursePublishes.add(coursePublish);
                }
        );
        // 0. 构建提示词
        prompt = String.format(prompt, JSON.toJSONString(coursePublishes));
        history.add(ChatMessage.withSystem(prompt));
        // Spring 提供的一个类，用于实现 Server-Sent Events (SSE)。它允许服务器向客户端推送实时数据流。
        SseEmitter emitter = new SseEmitter();
        // 1. 获取DEEPSEEK的聊天服务
        IChatService chatService = aiService.getChatService(PlatformType.DEEPSEEK);
        // 2. 添加问题到历史记录
        history.add(ChatMessage.withUser(question));
        // 2. 创建请求参数
        ChatCompletion chatCompletion = ChatCompletion.builder()
                .model(AIModelConstant.MODEL_DEEPSEEK_CHAT)
                .messages(history) // 添加完整历史消息
                .build();
        // 3. 创建线程池，异步发送流式数据
        // 创建一个新的单线程执行器，并提交一个任务来异步处理聊天请求。这确保了不会阻塞主线程。
        Executors.newSingleThreadExecutor().submit(() -> {
            try {
                // 创建一个自定义的监听器对象，用于接收ai聊天服务的响应数据,重写send方法，一接收到deepseek的响应就发送给前端
                SseListener sseListener = new SseListener() {
                    @Override
                    protected void send() {
                        try {
                            emitter.send(this.getCurrData());
                            log.debug(this.getCurrData());  // 打印当前发送的内容
                        } catch (IOException e) {
                            log.error("发送sse失败", e);
                            emitter.completeWithError(e);
                        }
                    }
                };
                emitter.onCompletion(() -> {
                    log.debug("完成");
                    log.debug("历史记录：{}", sseListener.getOutput().toString());
                    history.add(ChatMessage.withAssistant(sseListener.getOutput().toString()));
                    sseListener.getEventSource().cancel();
                });
                // 发送流式数据
                chatService.chatCompletionStream(chatCompletion, sseListener);
                // 完成后关闭连接
                emitter.complete();
            } catch (Exception e) {
                log.error("获取聊天流式数据失败", e);
                emitter.completeWithError(e);
            }
        });
        log.debug("历史记录：{}", history);
        return emitter;
    }
}

